package com.dangdi.util;

import com.dangdi.controller.websokectHandler;
import com.gexin.fastjson.JSON;
import gnu.io.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import util.PropertiesUtils;
import util.gFunction;

import javax.xml.bind.SchemaOutputResolver;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

public class JavaRs232 implements Runnable, SerialPortEventListener {
    /**
     * JDK Serial Version UID
     */
    private Boolean flag = true;
    Logger logger = LoggerFactory.getLogger(this.getClass());
    protected CommPortIdentifier portId;
    protected List<String> portList;
    protected SerialPort serialPort;
    protected OutputStream outputStream = null;
    protected InputStream inputStream = null;
    protected int sendCount, reciveCount;
    private String status = "";

    websokectHandler sokect = new websokectHandler();

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    /**
     * 扫描本机的所有COM端口
     *
     * @since 2012-3-23 上午12:02:42
     */
    public List<String> scanPorts() {
        List<String> list = new ArrayList<String>();
        portList = new ArrayList<String>();
        logger.info("正在扫描串口");
        Enumeration<?> en = CommPortIdentifier.getPortIdentifiers();
        CommPortIdentifier portId;
        logger.info("能用的串口有:");
        while (en.hasMoreElements()) {
            portId = (CommPortIdentifier) en.nextElement();
            if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
                String name = portId.getName();
                if (!portList.contains(name)) {
                    logger.info(name);
                    portList.add(name);
                }
            }
        }
        if (null == portList || portList.isEmpty()) {
            logger.info("未找到可用的串口");
            return list;
        }
        list = portList;
        return list;
    }

    /**
     * 打开串行端口
     *
     * @since 2012-3-23 上午12:03:07
     */
    public Map<String, Object> openSerialPort(String comName, int comRate, int conData, int comStop, int comParity) {
        // 获取要打开的端口
        Map<String, Object> map = new HashMap<>();
        try {
            portId = CommPortIdentifier.getPortIdentifier(comName);
        } catch (NoSuchPortException e) {
            logger.info("没有找到" + comName + "串行端口号!");
            map.put("msg", "没有找到" + comName + "串行端口号!");
            return map;
        }
        // 打开端口
        try {
            serialPort = (SerialPort) portId.open("JavaRs232", 2000);
            logger.info(comName + "号已打开！");
            map.put("msg", comName + "串口已打开!");
        } catch (PortInUseException e) {
            logger.info(comName + "串口被占用");
            map.put("msg", comName + "串口被占用");
            return map;
        }

        // 设置端口参数
        try {
            //波特率
            logger.info("初始化串口参数:");
            int rate = comRate;
            int data = conData;
            int stop = comStop;
            int parity = comParity;
            serialPort.setSerialPortParams(rate, data, stop, parity);
        } catch (UnsupportedCommOperationException e) {

        }

        // 打开端口的IO流管道
        try {
            outputStream = serialPort.getOutputStream();
            inputStream = serialPort.getInputStream();
            logger.info("打开io流管道");
            map.put("msg", "打开io流管道");
        } catch (IOException e) {
            logger.info(e.getMessage());
            logger.info("打开io流管道时发送错误");
            map.put("msg", "打开io流管道时发送错误");
        }

        // 给端口添加监听器
        try {
            serialPort.addEventListener(this);
            logger.info("io流管道添加监听器");
            map.put("msg", "io流管道添加监听器");
        } catch (TooManyListenersException e) {
            logger.info(e.getMessage());
            logger.info("io流管道添加监听器是发生错误");
            map.put("msg", "io流管道添加监听器是发生错误");
        }

        serialPort.notifyOnDataAvailable(true);
        logger.info("完全启动了");
        return map;
    }

    /**
     * 给串行端口发送数据
     *
     * @since 2012-3-23 上午12:05:00
     */
    public void sendDataToSeriaPort(int msg) {
        try {
            sendCount++;

            logger.info("发送消息=" + msg);
            outputStream.flush();

        } catch (IOException e) {
            logger.info(e.getMessage());
        }
        logger.info("发送:" + sendCount);
        logger.info("接收:" + reciveCount);
    }

    /**
     * 关闭串行端口
     *
     * @since 2012-3-23 上午12:05:28
     */
    public void closeSerialPort() {
        try {
            if (outputStream != null)
                outputStream.close();
            if (serialPort != null)
                serialPort.close();
            serialPort = null;
            logger.info("串口关闭");
            sendCount = 0;
            reciveCount = 0;
        } catch (Exception e) {
            logger.info("发生错误=" + e.getMessage());
        }
    }

    /**
     * 显示错误或警告信息
     * @param msg 信息
     * @since 2012-3-23 上午12:05:47
     */


    /**
     * 端口事件监听
     */
    public void serialEvent(SerialPortEvent event) {
        switch (event.getEventType()) {
            case SerialPortEvent.BI:
            case SerialPortEvent.OE:
            case SerialPortEvent.FE:
            case SerialPortEvent.PE:
            case SerialPortEvent.CD:
            case SerialPortEvent.CTS:
            case SerialPortEvent.DSR:
            case SerialPortEvent.RI:
            case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
                break;
            case SerialPortEvent.DATA_AVAILABLE:
                byte[] readBuffer = new byte[50];

                try {
                    Map map = new HashMap();
                    String filePath = System.getProperty("user.dir") + "\\conf.properties";
                    //定义修改配置文件的工具类
                    PropertiesUtils utils = new PropertiesUtils(filePath);
                    while (inputStream.available() > 0) {
                        inputStream.read(readBuffer);
                    }
                    logger.info("收到=" + gFunction.encodeHexStr(readBuffer).substring(0, 2));
                    StringBuilder receivedMsg = new StringBuilder("/-- ");
                    receivedMsg.append(new String(readBuffer).trim()).append(" --/\n");
                    logger.info(receivedMsg.toString());
//                    status=receivedMsg.toString();
                    setStatus(receivedMsg.toString());
                    map.put("comData", gFunction.encodeHexStr(readBuffer).substring(0, 2));
                    map.put("machine_type", utils.getKeyValue("terminalSymbol"));
                    map.put("terminalNumber", utils.getKeyValue("terminalNumber"));
                    map.put("from", "JavaRs232");
                    sokect.onMessage(JSON.toJSONString(map));
                    reciveCount++;
                    logger.info("发送:" + sendCount);
                    logger.info("接收:" + reciveCount);
                } catch (IOException e) {
                    logger.info("e.getMessage()");
                }
        }
    }

    public byte[] readFromPort() {

        byte[] bytes = null;
        try {
            // 获取buffer里的数据长度
            int bufflenth = inputStream.available();
            while (bufflenth != 0) {
                // 初始化byte数组为buffer中数据的长度
                bytes = new byte[bufflenth];
                inputStream.read(bytes);
                bufflenth = inputStream.available();
            }
        } catch (IOException e) {
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                    inputStream = null;
                }
            } catch (IOException e) {
            }
        }
        return bytes;
    }


    /**
     * 运行主函数
     *
     * @param args
     * @since 2012-3-23 上午12:06:45
     */
    public static void main(String[] args) {
    }

    @Override
    public void run() {
        flag = true;
        while (flag) {

        }
    }

    public Boolean getFlag() {
        return flag;
    }

    public void setFlag(Boolean flag) {
        this.flag = flag;
    }
}